global mblur_asm

section .data



section .text
;void mblur_asm    (
	;unsigned char *src,
	;unsigned char *dst,
	;int filas,
	;int cols,
	;int src_row_size,
	;int dst_row_size)

; RDI <- src
; RSI <- dst
; RDX <- columnas
; RCX <- filas
; R8  <- src_row_size
; R9  <- dst_row_size

%macro procesar_4_pixeles 5
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; paso todo a enteros de 32 bits desenpaquetando
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	PXOR XMM5, XMM5
	PUNPCKLBW %1, XMM5
	PUNPCKLWD %1, XMM5
	
	PXOR XMM5, XMM5
	PUNPCKLBW %2, XMM5
	PUNPCKLWD %2, XMM5
	
	PXOR XMM5, XMM5
	PUNPCKLBW %3, XMM5
	PUNPCKLWD %3, XMM5

	PXOR XMM5, XMM5
	PUNPCKLBW %4, XMM5
	PUNPCKLWD %4, XMM5

	PXOR XMM5, XMM5
	PUNPCKLBW %5, XMM5
	PUNPCKLWD %5, XMM5


	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; sumo las 5 filas relevanes
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	PADDD %1, %2
	PADDD %3, %4
	PADDD %1, %5
	PADDD %1, %3
	
	CVTDQ2PS %1, %1
	DIVPS %1, XMM15				; divido por 5 (multiplico por 0.2)
	CVTPS2DQ %1, %1

	PACKUSDW %1, %1        
	PACKUSWB %1, %1
%endmacro

mblur_asm:
	PUSH RBP
	MOV RBP, RSP
	PUSH RBX
	PUSH R12
	PUSH R13
        LEA RSP, [RSP - 8]

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; genero en xmm15 un registro que tiene todos los dwords = 5
	; esto lo voy a usar para dividir por 5 (o multiplicar por 0.2)
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	PXOR XMM15, XMM15
	MOV EAX, 5
	MOVD XMM15, EAX
	MOVUPS XMM14, XMM15
	PSLLDQ XMM15, 4
	PXOR XMM15, XMM14
	MOVUPS XMM14, XMM15
	PSLLDQ XMM14, 8
	PXOR XMM15, XMM14
	CVTDQ2PS XMM15, XMM15
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; limpio las partes altas de R8 y R9
	; se va a usar en el direccionamiento de memoria
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	SHL R8, 32
	SHR R8, 32
	SHL R9, 32
	SHR R9, 32
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; primero tengo que procesar las primeras dos filas
	XOR R12, R12
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	CICLO PRIMERAS DOS FILAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.ciclo_primeras_dos_filas:	
	CMP R12, 2
	JE .fin_primeras_dos_filas
	XOR RBX, RBX
	ADD RBX, 16
.ciclo_columnas_primeras_dos_filas:
	CMP EBX, R8d
	JG .ajustar_borde_fila_primeras_dos_filas
.pasaje:
	PXOR XMM0, XMM0
	MOVUPS [RSI + RBX - 16], XMM0
	CMP EBX, R8d
	JE .fin_fila_primeras_dos_filas	
	ADD EBX, 16
	JMP .ciclo_columnas_primeras_dos_filas
.fin_fila_primeras_dos_filas:
	ADD RSI, R9
	ADD RDI, R8
	INC R12
	JMP .ciclo_primeras_dos_filas
.ajustar_borde_fila_primeras_dos_filas:
	MOV EAX, EBX
	SUB EAX, R8d
	SUB EBX, EAX
	INC R12
	JMP .pasaje	
.fin_primeras_dos_filas:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 	FIN CICLO PRIMERAS DOS FILAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	; paso al cuerpo de la imagen sobre la que tengo que aplicar motion blur
	SUB ECX, 4
	ADD RDX, RDX
	ADD RDX, RDX								; este es la tamaño de la fila mas las 4 columnas del borde
	SUB RDX, 8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 	CUERPO PRINCIPAL SOBRE EL QUE SE APLICA MBLUR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.ciclo_filas_cuerpo_principal:
	CMP ECX, 0
	JE .fin_ciclo_principal
	XOR R13, R13	
	PXOR XMM0, XMM0								; paso en negro las primeras dos columnas
	MOVUPS [RSI], XMM0
	ADD R13, 24								; las primeras dos columnas 											; y 16 para ajustar el 											; borde								

.ciclo_columnas_cuerpo_principal:
	CMP R13d, EDX	
	JG .ajustar_ciclo_principal_fin_fila
.procesar:
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; obtengo información de las 4 filas relevantes
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	MOVUPS XMM0, [RDI + R13 - 16]
	SUB RDI, R8
	SUB RDI, R8
	SUB RDI, 8								; dos filas antes desplazado dos columnas hacia atrás
	MOVUPS XMM1, [RDI + R13 - 16]
	ADD RDI, R8
	ADD RDI, 4								; dos filas antes desplazado una columna hacia atrás
	MOVUPS XMM2, [RDI + R13 - 16]
	ADD RDI, R8
	ADD RDI, R8
	ADD RDI, 8								; una fila después desplazado una columna hacia delante
	MOVUPS XMM3, [RDI + R13 - 16]
	ADD RDI, R8
	ADD RDI, 4								; dos filas después desplazado dos columnas hacia adelante
	MOVUPS XMM4, [RDI + R13 - 16]
	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; me guardo la información que obtuve de memoria para no
	; ir a buscarla nuevamente
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;		
	MOVUPS XMM6, XMM0							
	MOVUPS XMM7, XMM1
	MOVUPS XMM8, XMM2
	MOVUPS XMM9, XMM3
	MOVUPS XMM10, XMM4
	
        procesar_4_pixeles XMM0, XMM1, XMM2, XMM3, XMM4

	PSLLDQ XMM0, 12
	PSRLDQ XMM0, 12

	MOVUPS XMM11, XMM0
	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; shifteo 4 bytes la informacion para seguir con el
	; píxel contiguo
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	PSRLDQ XMM6, 4
	PSRLDQ XMM7, 4
	PSRLDQ XMM8, 4
	PSRLDQ XMM9, 4
	PSRLDQ XMM10, 4
	
	MOVUPS XMM0, XMM6
	MOVUPS XMM1, XMM7
	MOVUPS XMM2, XMM8
	MOVUPS XMM3, XMM9
	MOVUPS XMM4, XMM10

        procesar_4_pixeles XMM0, XMM1, XMM2, XMM3, XMM4	
	
	PSLLDQ XMM0, 12
	PSRLDQ XMM0, 8

	PXOR XMM11, XMM0

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; shifteo 4 bytes la informacion para seguir con el
	; píxel contiguo
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	PSRLDQ XMM6, 4
	PSRLDQ XMM7, 4
	PSRLDQ XMM8, 4
	PSRLDQ XMM9, 4
	PSRLDQ XMM10, 4
	
	MOVUPS XMM0, XMM6
	MOVUPS XMM1, XMM7
	MOVUPS XMM2, XMM8
	MOVUPS XMM3, XMM9
	MOVUPS XMM4, XMM10

        procesar_4_pixeles XMM0, XMM1, XMM2, XMM3, XMM4	
	
        PSLLDQ XMM0, 12
	PSRLDQ XMM0, 4

	PXOR XMM11, XMM0

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; shifteo 4 bytes la informacion para seguir con el
	; píxel contiguo
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	
	PSRLDQ XMM6, 4
	PSRLDQ XMM7, 4
	PSRLDQ XMM8, 4
	PSRLDQ XMM9, 4
	PSRLDQ XMM10, 4
	
	MOVUPS XMM0, XMM6
	MOVUPS XMM1, XMM7
	MOVUPS XMM2, XMM8
	MOVUPS XMM3, XMM9
	MOVUPS XMM4, XMM10

        procesar_4_pixeles XMM0, XMM1, XMM2, XMM3, XMM4	
	
        PSLLDQ XMM0, 12

	PXOR XMM11, XMM0


	MOVUPS [RSI + R13 - 16], XMM11
	SUB RDI, 8
	SUB RDI, R8
	SUB RDI, R8
	CMP R13d, R8d
	JE .fin_ciclo_columnas_principal
	ADD R13, 16
	JMP .ciclo_columnas_cuerpo_principal
.ajustar_ciclo_principal_fin_fila:		
	MOV EAX, R13d
	SUB EAX, R8d
	SUB R13d, EAX
	JMP .procesar	

.fin_ciclo_columnas_principal:
	PXOR XMM0, XMM0
	MOVUPS [RSI + RBX - 8], XMM0
	ADD RDI, R8
	ADD RSI, R9
	DEC ECX
	JMP .ciclo_filas_cuerpo_principal

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 	FIN CUERPO PRINCIPAL SOBRE EL QUE SE APLICA MBLUR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.fin_ciclo_principal:
	XOR R12, R12
.ciclo_ultimas_dos_filas:	
	CMP R12, 2
	JE .fin
	XOR RBX, RBX
	ADD RBX, 16
.ciclo_columnas_ultimas_dos_filas:
	CMP EBX, R8d
	JG .ajustar_borde_fila_ultimas_dos_filas
.pasaje_ultimo:
	PXOR XMM0, XMM0
	MOVUPS [RSI + RBX - 16], XMM0
	CMP EBX, R8d
	JE .fin_fila_ultimas_dos_filas	
	ADD EBX, 16
	JMP .ciclo_columnas_ultimas_dos_filas
.fin_fila_ultimas_dos_filas:
	ADD RSI, R9
	ADD RDI, R8
	INC R12
	JMP .ciclo_ultimas_dos_filas
.ajustar_borde_fila_ultimas_dos_filas:
	MOV EAX, EBX
	SUB EAX, R8d
	SUB EBX, EAX
	INC R12
	JMP .pasaje_ultimo	

.fin:
	
	LEA RSP, [RSP + 8]
	POP R13
	POP R12
	POP RBX
	POP RBP
	RET 
